// FRAOZO - 3a
// Contains the main function, along with testSearch and
// testMatches as dictated in spec.

#include <iostream>
#include <string>
#include "grid.h"
#include "dictionary.h"

using namespace std;

void normalizeIdx(const grid &myGrid, int &newRow, int &newCol)
//Aviod out-of-range indexes
//If passed a row value of 30, it will return a row value of 0
// (ie first row)
{
   int totRows=myGrid.getRows();
   int totCols=myGrid.getCols();
   
   if (newRow<0)
      newRow+=totRows;;
   if (newCol<0)
      newCol+=totCols;

   if (newRow>=totRows)
      newRow-=totRows;
   if (newCol>=totCols)
      newCol-=totCols;
}

void findDir (const grid &myGrid, int row, int col, int hor, int ver, const string &myString)
//Similar to findAdj, but only searches in one direction
// which is determined by hor and ver offsets.
//We assume that the current string letter is myString[2]
{
   bool matches=false;
   
   //iterate through each remaining letter in myString
   for (int idx=2; idx<myString.size(); idx++)
   {
      //offset row and column by the direction of interest (ie, hor and ver)
      row = hor+row;
      col = ver+col;
      
      normalizeIdx(myGrid, row, col);
      
      if (myGrid.indexGrid(row,col) != myString[idx])
      {
	 matches = false;
	 break;
      }
      else 
	 matches=true;
   }

   //Only print matches that have at least 5 letters
   if (matches && myString.size() > 4)
      cout << myString << endl;

}

void findAdj (const grid &myGrid, int row, int col, const string &myString)
//(row, col) is the position of the starting letter
//Check every adjacent letter to the starting letter
{
   int newRow;
   int newCol;
   bool found1=false;
   
   //Examine the second letter
   int sIdx = 1;

   //for each horizontal direction
   for (int hor=-1; hor<=1; hor++)

      //For each vertical direction
      for (int ver=-1; ver<=1; ver++)
      {
	 if (hor == 0 && ver ==0)
	    continue;

	 //get the row/column of the adjacent letter to examine
	 newRow = hor+row;
	 newCol = ver+col;
	    
	 //Normalize the indeces (ie row -1 --> row 29 for 30x30 grid)
	 normalizeIdx(myGrid, newRow, newCol);

	 if (myGrid.indexGrid(newRow,newCol) == myString[sIdx])
	 {
	    found1 = true;
	    //Keep looking in the same direction determined by ver and hor
	    findDir(myGrid, newRow, newCol, hor, ver, myString);
	 }
      }

}

void findMatches (const grid &myGrid, const dictionary &myDict)
//Goes through each word in the dictionary and looks for a valid
//starting letter in the grid.  If so, calls findAdj to look for 
//correct adjacent letters
{
   //iterate through myDict
   for (int dIdx=0; dIdx<myDict.getSize(); dIdx++)
   {
      string myString=myDict.idxString(dIdx);

      //Iterate through every row in grid
      for (int row=0; row<myGrid.getRows(); row++)

	 //Iterate through every column in grid
	 for (int col=0; col<myGrid.getCols(); col++)
	    if (myGrid.indexGrid(row,col) == myString[0])
	       //Examine each adjacent letter
	       findAdj (myGrid, row, col, myString);

   }
}

string readKeyboard ()
//Reads the grid file name from the keyboard.
//For simplicity, we place in the possible inputxx
//files in the CWD.
{
   string fileName;
   cout << "Which grid file do you want to open?" << endl;
   cin >> fileName;
   return fileName;
}

void testSearch ()
//Sets up the program to look for matches
//by reading in the contents of the inputxx
//file, and the dictionary file
{
   //Instantiate and load the grid with the input file
   grid myGrid;
   string gridFileName = readKeyboard();
   myGrid.readInputFile(gridFileName);

   //Instantiate and load the dictionary with the input file
   dictionary myDict;
   string dictFileName = "dictionary";
   myDict.readInputFile(dictFileName);

   //Find word matches between the two
   findMatches(myGrid, myDict);

}   

int main (int argc, char* argv[]) 
{
   try
   {
      testSearch();
   }
   catch (baseException &err)
   {
      cerr << "Caught exception : " << err.what() << endl;
   }
   return 0;
}

